﻿using System.Runtime.CompilerServices;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.Validate;

namespace Shop.RemoteModel.ActivityDiscount.Model
{
    public class DiscountSet
    {
        /// <summary>
        /// 优惠门槛
        /// </summary>
        [EnumValidate("shop.activity.threshold.error", typeof(DiscountThreshold))]
        public DiscountThreshold Threshold { get; set; }


        /// <summary>
        /// 门槛价
        /// </summary>
        [NullValidate("shop.activity.discount.item.null")]
        [EntrustValidate("_Check")]
        public DiscountItem[] Items { get; set; }

        private static void _CheckGive (DiscountItem[] items)
        {
            long[] ids = items.Where(a => a.Mode == DiscountContent.送赠品 && a.GiveSkuId.HasValue).Select(a => a.GiveSkuId.Value).ToArray();
            if (ids.Distinct().Length != ids.Length)
            {
                throw new ErrorException("shop.activity.give.repeat");
            }
        }
        private static void _CheckAddPriceGive (DiscountItem[] items)
        {
            decimal[] price = items.Where(a => a.Mode == DiscountContent.加多少元送赠品 && a.ThresholdPrice.HasValue && a.AddPrice.HasValue).OrderBy(a => a.ThresholdPrice.Value).Select(a => a.AddPrice.Value).ToArray();
            if (price.Length > 1)
            {
                int end = price.Length - 1;
                for (int i = 0; i < end; i++)
                {
                    if (price[i] <= price[i + 1])
                    {
                        throw new ErrorException("shop.activity.add.price.error");
                    }
                }
            }
        }
        private static void _CheckCoupon (DiscountItem[] items)
        {
            long[] ids = items.Where(a => a.Mode == DiscountContent.送优惠卷 && a.CouponId.HasValue).Select(a => a.CouponId.Value).ToArray();
            if (ids.Distinct().Length != ids.Length)
            {
                throw new ErrorException("shop.activity.coupon.repeat");
            }
        }
        private static void _CheckReducePrice (DiscountItem[] items)
        {
            decimal[] price = items.Where(a => a.Mode == DiscountContent.减金额 && a.ThresholdPrice.HasValue && a.ReducePrice.HasValue).OrderBy(a => a.ThresholdPrice.Value).Select(a => a.ReducePrice.Value).ToArray();
            if (price.Length > 1)
            {
                int end = price.Length - 1;
                for (int i = 0; i < end; i++)
                {
                    if (price[i] >= price[i + 1])
                    {
                        throw new ErrorException("shop.activity.reduce.price.error");
                    }
                }
            }
        }

        private static void _CheckReduceNum (DiscountItem[] items)
        {
            int[] num = items.Where(a => a.ThresholdPrice.HasValue && a.Mode == DiscountContent.减件 && a.ReduceNum.HasValue).OrderBy(a => a.ThresholdPrice.Value).Select(a => a.ReduceNum.Value).ToArray();
            if (num.Length > 1)
            {
                int end = num.Length - 1;
                for (int i = 0; i < end; i++)
                {
                    if (num[i] >= num[i + 1])
                    {
                        throw new ErrorException("shop.activity.reduce.num.error");
                    }
                }
            }
        }
        private static void _CheckReduceNumPrice (DiscountItem[] items)
        {
            decimal[] price = items.Where(a => a.Mode == DiscountContent.减金额 && a.ReducePrice.HasValue && a.ThresholdNum.HasValue).OrderBy(a => a.ThresholdNum.Value).Select(a => a.ReducePrice.Value).ToArray();
            if (price.Length > 1)
            {
                int end = price.Length - 1;
                for (int i = 0; i < end; i++)
                {
                    if (price[i] >= price[i + 1])
                    {
                        throw new ErrorException("shop.activity.reduce.price.error");
                    }
                }
            }
        }
        private static void _CheckReduceRatio (DiscountItem[] items)
        {
            short[] radio = items.Where(a => a.Mode == DiscountContent.打折 && a.DiscountRatio.HasValue && a.ThresholdNum.HasValue).OrderBy(a => a.ThresholdNum.Value).Select(a => a.DiscountRatio.Value).ToArray();
            if (radio.Length > 1)
            {
                int end = radio.Length - 1;
                for (int i = 0; i < end; i++)
                {
                    if (radio[i] <= radio[i + 1])
                    {
                        throw new ErrorException("shop.activity.discount.radio.error");
                    }
                }
            }
        }
        private static void _CheckDiscountPrice (DiscountItem[] items)
        {
            decimal[] price = items.Where(a => a.Mode == DiscountContent.最低价商品享 && a.ThresholdNum.HasValue && a.DiscountPrice.HasValue).OrderBy(a => a.ThresholdNum.Value).Select(a => a.DiscountPrice.Value).ToArray();
            if (price.Length > 1)
            {
                int end = price.Length - 1;
                for (int i = 0; i < end; i++)
                {
                    if (price[i] <= price[i + 1])
                    {
                        throw new ErrorException("shop.activity.discount.price.error");
                    }
                }
            }
        }

        [MethodImplAttribute(MethodImplOptions.NoOptimization)]
        private static void _Check (DiscountSet source)
        {
            if (source.Items.Length == 1)
            {
                return;
            }
            if (source.Threshold == DiscountThreshold.无门槛)
            {
                _CheckGive(source.Items);
                _CheckCoupon(source.Items);
            }
            else if (source.Threshold == DiscountThreshold.每满减促销)
            {
                _CheckReducePrice(source.Items);
            }
            else if (source.Threshold == DiscountThreshold.满减促销)
            {
                if (source.Items.Count(a => a.Mode == DiscountContent.任选) > 1)
                {
                    throw new ErrorException("shop.activity.discount.mode.optional.repeat");
                }
                _CheckReducePrice(source.Items);
                _CheckGive(source.Items);
                _CheckCoupon(source.Items);
                _CheckAddPriceGive(source.Items);
            }
            else
            {
                _CheckReduceNumPrice(source.Items);
                _CheckReduceNum(source.Items);
                _CheckReduceRatio(source.Items);
                _CheckDiscountPrice(source.Items);
            }
        }

    }
}
